package com.jms.framework.beans.utils;

import com.jms.framework.aware.ApplicationContextAware;
import com.jms.framework.aware.ApplicationContextAwareInitializer;
import com.jms.framework.beans.BeanDefinition;
import com.jms.framework.beans.ChildBeanDefinition;
import com.jms.framework.beans.GeneralBeanDefinition;
import com.jms.framework.beans.annotation.Bean;
import com.jms.framework.beans.annotation.Component;
import com.jms.framework.beans.annotation.Configuration;
import com.jms.framework.beans.exception.BeansException;
import com.jms.tools.util.AnnotationUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * Bean初始化工具类，提供获取Bean名称、类型和定义的静态方法
 * @author jms
 * @version 1.0.0
 * @since 20250124
 */
public class BeanInitializeUtils {

    /**
     * 私有构造方法，防止实例化
     */
    private BeanInitializeUtils() {

    }

    /**
     * 获取Bean的名称
     *
     * @param clazz    Bean的类
     * @param beanName 自定义的Bean名称，如果未提供或为空，则根据类名生成
     * @return Bean的名称
     */
    public static String getBeanName(Class<?> clazz, String beanName) {
        if (beanName == null || beanName.equals("")) {
            beanName = clazz.getSimpleName();
            beanName = beanName.substring(0, 1).toLowerCase() + beanName.substring(1);
        }
        return beanName;
    }

    /**
     * 判断给定的类是否是一个Bean
     *
     * @param clazz 要判断的类
     * @return 如果类上标注了@Component、@Controller、@Configuration、@Service或@Repository注解，则返回true，否则返回false
     */
    public static boolean isBean(Class<?> clazz) {
        return AnnotationUtils.hasAnnotation(clazz, Component.class);
    }

    /**
     * 创建Bean的定义
     *
     * @param clazz Bean的类
     * @return Bean的定义对象，如果类是Bean，则根据其注解返回对应的BeanDefinition实现，否则返回null
     */
    public static BeanDefinition createBeanDefinition(Class<?> clazz) {
        try {
            if (isBean(clazz)) {
                Annotation annotation = AnnotationUtils.getAnnotationByTargetAnnotation(clazz, Component.class);
                if (annotation == null) {
                    return null;
                }
                String value = AnnotationUtils.getAnnotationProperty(annotation, "value");
                boolean lazy = AnnotationUtils.getAnnotationProperty(annotation, "lazy");
                String scope = AnnotationUtils.getAnnotationProperty(annotation, "scope");
                int orderNumber = AnnotationUtils.getAnnotationProperty(annotation, "orderNumber");
                boolean afterInit = AnnotationUtils.getAnnotationProperty(annotation, "afterInit");
                return new GeneralBeanDefinition(getBeanName(clazz, value), clazz, scope, lazy, orderNumber, afterInit);
            }
        } catch (Exception e) {
            throw new BeansException(e);
        }
        return null;
    }

    /**
     * 判断给定的类是否实现了ApplicationContextAware接口
     *
     * @param clazz 要判断的类
     * @return 如果类实现了ApplicationContextAware接口，则返回true，否则返回false
     */
    public static boolean isAware(Class<?> clazz) {
        return ApplicationContextAware.class.isAssignableFrom(clazz);
    }

    /**
     * 初始化实现了ApplicationContextAware接口的Bean
     *
     * @param aware 实现了ApplicationContextAware接口的Bean
     */
    public static void initAware(ApplicationContextAware aware) {
        ApplicationContextAwareInitializer.getInstance().initApplicationContextAware(aware);
    }

    /**
     * 从配置类中获取Bean的定义列表
     *
     * @param configClass 配置类
     * @param configBeanName 配置类的Bean名称
     * @return 包含配置类中定义的所有Bean的列表
     */
    public static List<BeanDefinition> getBeanDefinitionsFromConfiguration(Class<?> configClass, String configBeanName) {
        List<BeanDefinition> beanDefinitions = new LinkedList<>();
        if (AnnotationUtils.hasAnnotation(configClass, Configuration.class)) {
            Method[] methods = configClass.getMethods();
            for (Method method : methods) {
                if (method.isAnnotationPresent(Bean.class)) {
                    Bean bean = method.getAnnotation(Bean.class);
                    Class<?> beanClass = method.getReturnType();
                    if (beanClass == void.class) {
                        throw new BeansException("the bean class is void");
                    }
                    beanDefinitions.add(new ChildBeanDefinition(getBeanName(beanClass, bean.value()), beanClass, bean.scope(), bean.lazy(), configClass, configBeanName, method.getName(), bean.orderNumber(), bean.afterInit()));
                }
            }
        }
        return beanDefinitions;
    }

    /**
     * 对Bean定义列表进行排序
     * @param beanNames Bean名称列表
     * @param beanDefinitions Bean定义列表
     */
    public static void sortBeanDefinitions(List<String> beanNames, Map<String, BeanDefinition> beanDefinitions) {
        beanNames.sort((beanName1, beanName2) -> {
            BeanDefinition beanDefinition1 = beanDefinitions.get(beanName1);
            BeanDefinition beanDefinition2 = beanDefinitions.get(beanName2);
            return beanDefinition1.getOrderNumber() - beanDefinition2.getOrderNumber();
        });
    }
}
